package ar.edu.utn.frsf.cidisi.ginet.verification.formalmodel;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.pnml.tools.epnk.pnmlcoremodel.PetriNet;

import ar.edu.utn.frsf.cidisi.ginet.formalization.FormalCBPLanguage;
import ar.edu.utn.frsf.cidisi.ginet.formalization.RootElement;
import ar.edu.utn.frsf.cidisi.ginet.generation.choreography2ginet.Choreography2GINet;
import ar.edu.utn.frsf.cidisi.ginet.generation.pnml2cpntools.Pnml2CpnTools;

public class FormalModel {
	
//	private RootElement root;
	private Resource resourceFormalization;
	private Resource resourceCbpModel;
//	private EClass rootClass;
	private EObject rootElement;
	
	public FormalModel(IFile cbpFile) {

		String path = cbpFile.getProject().getFullPath().toString();
//		String fileName = element.eResource().getURI().lastSegment();
		String newFileName = path + "/model/upcolbpip.formalization";

		
		ResourceSet resourceSetFormal = new ResourceSetImpl();

		URI formalModelURI = URI.createPlatformResourceURI(newFileName, true);

		resourceFormalization = resourceSetFormal.getResource(formalModelURI, true);
		
		ResourceSet resourceSetCBP = new ResourceSetImpl();

		URI cbpModelURI = URI.createPlatformResourceURI(cbpFile.getFullPath().toString(), true);

		resourceCbpModel = resourceSetCBP.getResource(cbpModelURI, true);
	
	}
	
	public void generateFormalModel(){
		
		FormalCBPLanguage formalLanguage = null;
		if (resourceFormalization.getContents().get(0) instanceof FormalCBPLanguage){
			
			formalLanguage = (FormalCBPLanguage)resourceFormalization.getContents().get(0);
			
			EObject rootElement = findRootElement(resourceCbpModel.getContents(), formalLanguage.getRootElement().getElement());
			
//			if (resourceCbpModel.getContents())

			Choreography2GINet cbp2ginet = new Choreography2GINet(formalLanguage, rootElement);
			
			cbp2ginet.generateGINet();

			// Get the resource path 
			String path = resourceFormalization.getURI().path();
			
			// Get the file name
			String fileName = resourceFormalization.getURI().lastSegment();
			
			// The full path to the new PNML file
			String pnmlFileName = path.substring(0, path.indexOf(fileName)) + "cgim.pnml";

			// Saves the GI-Net to a file
			cbp2ginet.saveGINet(pnmlFileName);
			
			// The full path to the new PNML file
			String cpnFileName = path.substring(9, path.indexOf(fileName)) + "cgim.cpn";
			
			// Saves the PNML file to a CPN file
			Pnml2CpnTools pnml2cpn = new Pnml2CpnTools(cbp2ginet.getGINet());
			pnml2cpn.generateCPN();
			pnml2cpn.export(ResourcesPlugin.getWorkspace().getRoot().getLocation()+cpnFileName);
			
//			// Refresh the workspace in order to show pnml and cpn files
//			try {
//				IContainer container = ResourcesPlugin.getWorkspace().getRoot().getContainerForLocation(new Path(ResourcesPlugin.getWorkspace().getRoot().getLocation()+path.substring(0, path.indexOf(fileName))));
//				container.refreshLocal(IContainer.DEPTH_INFINITE, null);
//			} catch (CoreException e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			}
			
		}

		
	}
	
	
	/**
	 * Search in the list of {@code elements} the element of class {@code elementClass}
	 * 
	 * @param elements List of elements
	 * @param elementClass Class of the element to search in the list of elements
	 * @return The element, if it's found. Null otherwise.
	 *
	 * jmr
	 */
	private EObject findRootElement(EList<EObject> elements, EClass elementClass){
		
		for (EObject obj : elements){
			
			if (obj.eClass().getName().equals(elementClass.getName())){
				
				return obj;
				
			} else if (!obj.eContents().isEmpty()){
				
				EObject rootElement = findRootElement(obj.eContents(), elementClass);
				
				if (rootElement != null){
					
					return rootElement;
					
				}
				
			}
		}
		
		return null;
	}


}
